/* Copyright(C) 2006-2008 Dave Sexton  *
 * http://www.codeplex.com/aip         *
 * http://www.codeplex.com/aip/license *
 ***************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace DaveSexton.Web.Controls
{
	/// <summary>
	/// An abstract base class that implements <see cref="AutoInputProtectionImageProvider"/> for creating instances of 
	/// <see cref="PartitionedAutoInputProtectionImage"/>, which renders the text generated by an implementation of 
	/// <see cref="AutoInputProtectionTextProvider"/> by segregating individual characters into even spaced veritcal partitions 
	/// and uses randomized colors, fonts and rotations.
	/// </summary>
	/// <remarks>
	/// <para>
	/// <see cref="PartitionedAutoInputProtectionImageProvider"/> is a factory that creates instances of <see cref="PartitionedAutoInputProtectionImage"/>.
	/// </para>
	/// <para>
	/// Derived types can use the <see cref="GenerateImage(Size,AutoInputProtectionTextProvider)"/> method to easily create an instance of 
	/// <see cref="PartitionedAutoInputProtectionImage"/>, which is then returned by the type's implementations of 
	/// <see cref="GenerateAutoInputProtectionImage"/> and <see cref="GenerateRandomAutoInputProtectionImage"/>.
	/// </para>
	/// </remarks>
	/// <include file='examples.xml' path='//example[@id="Partitioned"][@type="images"]'/>
	/// <include file='examples.xml' path='//example[@id="Partitioned"][@type="config"]'/>
	/// <seealso cref="PartitionedAutoInputProtectionImage"/>
	/// <seealso cref="AutoInputProtection.DefaultImageProvider"/>
	/// <seealso cref="Configuration.AutoInputProtectionSection"/>
	/// <seealso cref="AutoInputProtectionTextProvider"/>
	/// <seealso cref="AutoInputProtectionFilterProvider"/>
	public abstract class PartitionedAutoInputProtectionImageProvider : AutoInputProtectionImageProvider
	{
		#region Public Properties
		/// <summary>
		/// Gets or sets the left, right, bottom and top margins from the edges of the image in which the text will be rendered, in pixels.
		/// </summary>
		/// <value>The margin in which the text will be rendered, in pixels.</value>
		public int Margin
		{
			get
			{
				return margin;
			}
			set
			{
				margin = value;
			}
		}

		/// <summary>
		/// Gets or sets the minimum amount, in degrees, of random rotation that is applied to each character.
		/// </summary>
		/// <value>The minimum amount, in degrees, of random rotation that is applied to each character.</value>
		public int MinimumCharacterRotation
		{
			get
			{
				return minRotation;
			}
			set
			{
				// negatives are allowed
				minRotation = value;
			}
		}

		/// <summary>
		/// Gets or sets the maximum amount, in degrees, of random rotation that is applied to each character.
		/// </summary>
		/// <value>The maximum amount, in degrees, of random rotation that is applied to each character</value>
		public int MaximumCharacterRotation
		{
			get
			{
				return maxRotation;
			}
			set
			{
				// negatives are allowed
				maxRotation = value;
			}
		}
		#endregion

		#region Private / Protected
		private int margin, minRotation, maxRotation;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="PartitionedAutoInputProtectionImageProvider" /> class for derived classes.
		/// </summary>
		protected PartitionedAutoInputProtectionImageProvider()
		{
		}
		#endregion

		#region Methods
		/// <summary>
		/// Loads the provider's settings from the specified <paramref name="config"/>.
		/// </summary>
		/// <exception cref="System.Configuration.Provider.ProviderException">An attribute value cannot be converted into the required type.</exception>
		/// <param name="name">Name of the provider.</param>
		/// <param name="config">A collection of name and value pairs that will be used to initialize the provider.</param>
		public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
		{
			if (config == null)
				throw new ArgumentNullException("config");

			base.Initialize(name, config);

			ProviderHelper helper = new ProviderHelper(config);

			margin = helper.ParseInt32("margin", false, -1);
			minRotation = helper.ParseInt32("minimumCharacterRotation", false, -1);
			maxRotation = helper.ParseInt32("maximumCharacterRotation", false, -1);
		}

		/// <summary>
		/// Creates an instance of <see cref="PartitionedAutoInputProtectionImage"/> for the specified <paramref name="background"/>
		/// image and <paramref name="textProvider"/>.
		/// </summary>
		/// <remarks>
		/// Derived types can override this method to return a type that either composites or derives from 
		/// <see cref="PartitionedAutoInputProtectionImage"/>.
		/// </remarks>
		/// <seealso cref="GenerateAutoInputProtectionImage(string,Size,AutoInputProtectionTextProvider)"/>
		/// <param name="background">The <see cref="Image"/> that is used as the surface on which the text is rendered.</param>
		/// <param name="textProvider">The <see cref="AutoInputProtectionTextProvider"/> implementation that generates the text to be rendered.</param>
		/// <returns>An instance of <see cref="PartitionedAutoInputProtectionImage"/> for the specified <paramref name="background"/>
		/// image and <paramref name="textProvider"/>.</returns>
		protected virtual PartitionedAutoInputProtectionImage GenerateImage(Image background, AutoInputProtectionTextProvider textProvider)
		{
			PartitionedAutoInputProtectionImage image = new PartitionedAutoInputProtectionImage(background, textProvider);

			if (margin != -1)
				image.Margin = margin;

			if (minRotation != -1)
				image.MinimumCharacterRotation = minRotation;

			if (maxRotation != -1)
				image.MaximumCharacterRotation = maxRotation;

			return image;
		}

		/// <summary>
		/// Creates an instance of <see cref="PartitionedAutoInputProtectionImage"/> for the specified <paramref name="size"/>
		/// and <paramref name="textProvider"/>.
		/// </summary>
		/// <remarks>
		/// Derived types can override this method to return a type that either composites or derives from 
		/// <see cref="PartitionedAutoInputProtectionImage"/>.
		/// </remarks>
		/// <seealso cref="GenerateRandomAutoInputProtectionImage(Size,AutoInputProtectionTextProvider)"/>
		/// <param name="size">The dimensions of the image.</param>
		/// <param name="textProvider">The <see cref="AutoInputProtectionTextProvider"/> implementation that generates the text to be rendered.</param>
		/// <returns>An instance of <see cref="PartitionedAutoInputProtectionImage"/> for the specified <paramref name="size"/>
		/// and <paramref name="textProvider"/>.</returns>
		protected virtual PartitionedAutoInputProtectionImage GenerateImage(Size size, AutoInputProtectionTextProvider textProvider)
		{
			PartitionedAutoInputProtectionImage image = new PartitionedAutoInputProtectionImage(size, textProvider);

			if (margin != -1)
				image.Margin = margin;

			if (minRotation != -1)
				image.MinimumCharacterRotation = minRotation;

			if (maxRotation != -1)
				image.MaximumCharacterRotation = maxRotation;

			return image;
		}

		/// <summary>
		/// When implemented by a derived type, creates an instance of a type that derives from <see cref="AutoInputProtectionImage"/>
		/// that generates an image of the specified <paramref name="size"/>, using the specified <paramref name="name"/> and 
		/// <paramref name="textProvider"/>.
		/// </summary>
		/// <remarks>
		/// <para>
		/// Derived types are not required to use the <paramref name="name"/> argument.  This overload is not used by the 
		/// <see cref="AutoInputProtectionControl"/> control.
		/// </para>
		/// <para>
		/// A derived type can use the specified <paramref name="name"/> to load or generate a background <see cref="Image"/> 
		/// that is passed to <see cref="GenerateImage(Image,AutoInputProtectionTextProvider)"/>, which creates an instance of 
		/// <see cref="PartitionedAutoInputProtectionImage"/> that is then returned to the caller immediately or wrapped by a specialized class that
		/// is returned instead.  Alternatively, a derived type may override <see cref="GenerateImage(Image,AutoInputProtectionTextProvider)"/> to 
		/// create a custom implementation that is then returned by this method as is.
		/// </para>
		/// <para>
		/// See <see cref="ResourceAutoInputProtectionImageProvider"/> for information about one particular usage of the <paramref name="name"/> argument.
		/// </para>
		/// </remarks>
		/// <seealso cref="AutoInputProtection.GenerateAutoInputProtectionImage"/>
		/// <seealso cref="GenerateRandomAutoInputProtectionImage"/>
		/// <param name="name"><see cref="String"/> that identifies a particular named resource, style or image.</param>
		/// <param name="size">The dimensions of the image.</param>
		/// <param name="textProvider"><see cref="AutoInputProtectionTextProvider"/> implementation to be used by the <see cref="AutoInputProtectionImage"/> implementation that is created.</param>
		/// <returns>An <see cref="AutoInputProtectionImage"/> implementation that can generate an image of the specified <paramref name="size"/> using the specified
		/// <paramref name="textProvider"/>.</returns>
		public abstract override AutoInputProtectionImage GenerateAutoInputProtectionImage(string name, Size size, AutoInputProtectionTextProvider textProvider);

		/// <summary>
		/// When implemented by a derived type, creates an instance of a type that derives from <see cref="AutoInputProtectionImage"/>
		/// that generates an image of the specified <paramref name="size"/> using the specified <paramref name="textProvider"/>.
		/// </summary>
		/// <remarks>
		/// <para>
		/// This overload is used by the <see cref="AutoInputProtectionControl"/> control.
		/// </para>
		/// <para>
		/// A derived type can call <see cref="GenerateImage(Size,AutoInputProtectionTextProvider)"/> to create an instance of 
		/// <see cref="PartitionedAutoInputProtectionImage"/>, which can then be returned to the caller immediately or it can be wrapped by a specialied class that 
		/// is returned instead.  Alternatively, a derived type may override <see cref="GenerateImage(Size,AutoInputProtectionTextProvider)"/> to create a custom 
		/// implementation that is then returned by this method as is.
		/// </para>
		/// </remarks>
		/// <seealso cref="AutoInputProtection.GenerateAutoInputProtectionImage"/>
		/// <seealso cref="GenerateAutoInputProtectionImage"/>
		/// <param name="size">The dimensions of the image.</param>
		/// <param name="textProvider"><see cref="AutoInputProtectionTextProvider"/> implementation to be used by the <see cref="AutoInputProtectionImage"/> implementation that is created.</param>
		/// <returns>An <see cref="AutoInputProtectionImage"/> implementation that can generate an image of the specified <paramref name="size"/> using the specified
		/// <paramref name="textProvider"/>.</returns>
		public abstract override AutoInputProtectionImage GenerateRandomAutoInputProtectionImage(Size size, AutoInputProtectionTextProvider textProvider);
		#endregion
	}
}
